package com.heima.file.service.impl;

import com.heima.file.config.MinioConfig;
import com.heima.file.config.MinioConfigProperties;
import com.heima.file.service.FileStorageService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@EnableConfigurationProperties(MinioConfigProperties.class)
@Import(MinioConfig.class)
public class MinioFileStorageService implements FileStorageService {

  @Autowired private MinioClient minioClient;

  @Autowired private MinioConfigProperties minIOConfigProperties;

  private static final String separator = "/";

  /**
   * @param dirPath
   * @param filename yyyy/mm/dd/file.jpg
   * @return
   */
  public String builderFilePath(String dirPath, String filename) {
    StringBuilder stringBuilder = new StringBuilder(50);
    if (!StringUtils.isEmpty(dirPath)) {
      stringBuilder.append(dirPath).append(separator);
    }
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
    String todayStr = sdf.format(new Date());
    stringBuilder.append(todayStr).append(separator);
    stringBuilder.append(filename);
    return stringBuilder.toString();
  }

  /**
   * 上传图片文件
   *
   * @param prefix 文件前缀
   * @param filename 文件名
   * @param inputStream 文件流
   * @return 文件全路径
   */
  @Override
  public String uploadImgFile(String prefix, String filename, InputStream inputStream) {
    String filePath = builderFilePath(prefix, filename);
    try {
      PutObjectArgs putObjectArgs =
          PutObjectArgs.builder()
              .object(filePath)
              .contentType("image/jpg")
              .bucket(minIOConfigProperties.getBucket())
              .stream(inputStream, inputStream.available(), -1)
              .build();
      minioClient.putObject(putObjectArgs);
      StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
      urlPath.append(separator + minIOConfigProperties.getBucket());
      urlPath.append(separator);
      urlPath.append(filePath);
      return urlPath.toString();
    } catch (Exception ex) {
      log.error("minio put file error.", ex);
      throw new RuntimeException("上传文件失败");
    }
  }

  /**
   * 上传html文件
   *
   * @param prefix 文件前缀
   * @param filename 文件名
   * @param inputStream 文件流
   * @return 文件全路径
   */
  @Override
  public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
    String filePath = builderFilePath(prefix, filename);
    try {
      PutObjectArgs putObjectArgs =
          PutObjectArgs.builder()
              .object(filePath)
              .contentType("text/html")
              .bucket(minIOConfigProperties.getBucket())
              .stream(inputStream, inputStream.available(), -1)
              .build();
      minioClient.putObject(putObjectArgs);
      StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
      urlPath.append(separator + minIOConfigProperties.getBucket());
      urlPath.append(separator);
      urlPath.append(filePath);
      return urlPath.toString();
    } catch (Exception ex) {
      log.error("minio put file error.", ex);
      ex.printStackTrace();
      throw new RuntimeException("上传文件失败");
    }
  }

  /**
   * 删除文件
   *
   * @param pathUrl 文件全路径
   */
  @Override
  public void delete(String pathUrl) {
    String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");
    int index = key.indexOf(separator);
    String bucket = key.substring(0, index);
    String filePath = key.substring(index + 1);
    // 删除Objects
    RemoveObjectArgs removeObjectArgs =
        RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
    try {
      minioClient.removeObject(removeObjectArgs);
    } catch (Exception e) {
      log.error("minio remove file error.  pathUrl:{}", pathUrl);
      e.printStackTrace();
    }
  }

  /**
   * 下载文件
   *
   * @param pathUrl 文件全路径
   * @return 文件流
   */
  @Override
  public byte[] downLoadFile(String pathUrl) {
    String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");
    int index = key.indexOf(separator);
    String bucket = key.substring(0, index);
    String filePath = key.substring(index + 1);
    InputStream inputStream = null;
    try {
      inputStream =
          minioClient.getObject(
              GetObjectArgs.builder()
                  .bucket(minIOConfigProperties.getBucket())
                  .object(filePath)
                  .build());
    } catch (Exception e) {
      log.error("minio down file error.  pathUrl:{}", pathUrl);
      e.printStackTrace();
    }

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    byte[] buff = new byte[100];
    int rc = 0;
    while (true) {
      try {
        if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;
      } catch (IOException e) {
        e.printStackTrace();
      }
      byteArrayOutputStream.write(buff, 0, rc);
    }
    return byteArrayOutputStream.toByteArray();
  }
}
